From 25620c07109a346adaf2303cdca4e84e0a817d70 Mon Sep 17 00:00:00 2001 From: "kaf24@scramble.cl.cam.ac.uk" Date: Thu, 17 Jul 2003 20:49:37 +0000 Subject: [PATCH] bitkeeper revision 1.362 (3f170be1KkQ_xBzWAe6JSR2i5ZRyAg) config.h, xen_kbd.c: Cleaned up Xen keyboard/mouse virtualisation and fixed an infinite-loop bug in the interrupt handler. --- xen/drivers/char/xen_kbd.c | 310 ++++++++++++++++--------------------- xen/include/xeno/config.h | 2 + 2 files changed, 134 insertions(+), 178 deletions(-) diff --git a/xen/drivers/char/xen_kbd.c b/xen/drivers/char/xen_kbd.c index 065f2f7c39..0190055a33 100644 --- a/xen/drivers/char/xen_kbd.c +++ b/xen/drivers/char/xen_kbd.c @@ -1,9 +1,10 @@ #include #include -#include /* this has request_irq() proto for some reason */ +#include #include #include #include +#include /* Hash-defines torn from and */ @@ -25,92 +26,55 @@ #define kbd_read_input() inb(KBD_DATA_REG) #define kbd_read_status() inb(KBD_STATUS_REG) -#define KEYBOARD_IRQ 1 +#define KEYBOARD_IRQ 1 +#define AUX_IRQ 12 + #define kbd_write_output(val) outb(val, KBD_DATA_REG) #define kbd_write_command(val) outb(val, KBD_CNTL_REG) -#define AUX_IRQ 12 - -#undef KBD_DEBUG - -/* THIS SECTION DEALS WITH CONFIG_XEN_ATTENTION_KEY */ - -// always set for now. potentially moved to a central config later. -// this should really affect common/keyhandler.c too -#define CONFIG_XEN_ATTENTION_KEY - #ifdef CONFIG_XEN_ATTENTION_KEY static int xen_attention_key_down = 0; -#define XEN_ATTENTION_KEY 0x46 // scroll lock +#define XEN_ATTENTION_KEY 0x46 /* Scroll Lock */ #define KBD_SCANCODE_KEYUP_MASK 0x80 -/* naive scancode -> key mappings for internal xen use */ +/* Simple scancode-to-key mappings for internal Xen use. */ static unsigned char keymap_normal[] = { - 0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t', - 'q','w','e','r', 't','y','u','i', 'o','p','[',']','\r', 0 ,'a','s', - 'd','f','g','h', 'j','k','l',';', '\'','`', 0 ,'#', 'z','x','c','v', - 'b','n','m',',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + 0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t', + 'q','w','e','r', 't','y','u','i', 'o','p','[',']','\r', 0 ,'a','s', + 'd','f','g','h', 'j','k','l',';', '\'','`', 0 ,'#', 'z','x','c','v', + 'b','n','m',',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; static unsigned char keymap_shift[] = { - 0 , 0 ,'!','"', '#','$','%','^', '&','*','(',')', '_','+','\b','\t', - 'Q','W','E','R', 'T','Y','U','I', 'O','P','{','}','\r', 0 ,'A','S', - 'D','F','G','H', 'J','K','L',':', '@', 0 , 0 ,'~', 'Z','X','C','V', - 'B','N','M','<', '>','?', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 ,'|', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 -}; - - -static unsigned char keymap_control[] = -{ /* same as normal, except for a-z -> 1 to 26 */ - 0 , 0 ,'1','2', '3','4','5','6', '7','8','9','0', '-','=','\b','\t', - 17, 23, 5 , 18, 20, 25, 21, 9 , 15, 16,'[',']','\r', 0 , 1 , 19, - 4 , 6 , 7 , 8 , 10, 11, 12,';', '\'','`', 0 ,'#', 26, 24, 3 , 22, - 2 , 14, 13,',', '.','/', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 ,'\\', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , - 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 + 0 , 0 ,'!','"', '#','$','%','^', '&','*','(',')', '_','+','\b','\t', + 'Q','W','E','R', 'T','Y','U','I', 'O','P','{','}','\r', 0 ,'A','S', + 'D','F','G','H', 'J','K','L',':', '@', 0 , 0 ,'~', 'Z','X','C','V', + 'B','N','M','<', '>','?', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 ,'|', 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , + 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 }; static int keyboard_shift = 0; -static int keyboard_control = 0; -static int keyboard_echo = 0; static unsigned char convert_scancode (unsigned char scancode) { unsigned char value = 0; - switch (scancode) { - - case 0xbb: /* F1 */ - keyboard_echo = !keyboard_echo; - break; - - case 0xba: /* caps lock UP */ - case 0x9d: /* ctrl (left) UP */ - keyboard_control = 0; - break; - - case 0x3a: /* caps lock DOWN */ - case 0x1d: /* ctrl (left) DOWN */ - keyboard_control = 1; - break; + switch ( scancode ) + { case 0xaa: /* shift (left) UP */ case 0xb6: /* shift (right) UP */ @@ -122,151 +86,141 @@ static unsigned char convert_scancode (unsigned char scancode) keyboard_shift = 1; break; - default: /* normal keys */ - // dont process key-down events - if(!(scancode & KBD_SCANCODE_KEYUP_MASK)) break; - - scancode = scancode & (~KBD_SCANCODE_KEYUP_MASK); - if (keyboard_control) - value = keymap_control[scancode]; - else if (keyboard_shift) + default: + /* Only process key-up events */ + if(!(scancode & KBD_SCANCODE_KEYUP_MASK)) + break; + scancode = scancode & ~KBD_SCANCODE_KEYUP_MASK; + if (keyboard_shift) value = keymap_shift[scancode]; else value = keymap_normal[scancode]; - + break; } - if (value && keyboard_echo) printk ("%c", value); - return value; } #endif /* CONFIG_XEN_ATTENTION_KEY */ -/* THIS SECTION DEALS WITH STORING A RING OF PENDING KBD EVENTS */ - -// store kbd events waiting to be processed by guest os -#define KBD_RING_SIZE 64 +/* We store kbd events awaiting receive by a guest OS in a ring buffer. */ +#define KBD_RING_SIZE 64 static int kbd_ring[KBD_RING_SIZE]; static int kbd_ring_prod = 0; static int kbd_ring_cons = 0; -#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1)) -#define KBD_RING_FULL (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons) -#define KBD_RING_EMPTY (kbd_ring_prod == kbd_ring_cons) - -// these assume locking has already been taken care of -static void kbd_ring_push(unsigned char status, unsigned char scancode) { - if(KBD_RING_FULL) return; - kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status); - kbd_ring_prod = KBD_RING_INC(kbd_ring_prod); -} +#define KBD_RING_INC(_i) (((_i)+1) & (KBD_RING_SIZE-1)) +#define KBD_RING_FULL (KBD_RING_INC(kbd_ring_prod) == kbd_ring_cons) +#define KBD_RING_EMPTY (kbd_ring_prod == kbd_ring_cons) -static int kbd_ring_pop() { - int ret; - if(KBD_RING_EMPTY) { - // read directly from controller - no events waiting in ring - unsigned char status = kbd_read_status(); - unsigned char scancode = kbd_read_input(); - return KBD_CODE(scancode, status); - } - ret = kbd_ring[kbd_ring_cons]; - kbd_ring_cons = KBD_RING_INC(kbd_ring_cons); - return ret; +static void kbd_ring_push(unsigned char status, unsigned char scancode) +{ + if ( KBD_RING_FULL ) + return; + + kbd_ring[kbd_ring_prod] = KBD_CODE(scancode, status); + kbd_ring_prod = KBD_RING_INC(kbd_ring_prod); } +static int kbd_ring_pop(void) +{ + int ret; + + if ( KBD_RING_EMPTY ) + { + /* Read directly from controller - no events waiting in ring. */ + unsigned char status = kbd_read_status(); + unsigned char scancode = kbd_read_input(); + ret = KBD_CODE(scancode, status); + } + else + { + ret = kbd_ring[kbd_ring_cons]; + kbd_ring_cons = KBD_RING_INC(kbd_ring_cons); + } -/* THIS SECTION DEALS WITH COMMUNICATING PS2 EVENTS/CMDS WITH GUEST OS */ + return ret; +} -#include -// need lock as there may be _two_ interrupts at play, keyboard and mouse, as well as guest os actions +/* + * NB. Lock is essential as there are two distinct interrupts (keyboard + aux). + * Also interrupts may disturb guest OS actions. + */ static spinlock_t kbd_lock; - long do_kbd_op(unsigned char op, unsigned char val) { - // check for domain 0 -#ifdef KBD_DEBUG - printk("do_kbd_op: op %2x, val %2x, prod %d, cons %d\n", op, val, kbd_ring_prod, kbd_ring_cons); -#endif + unsigned long flags; + long ret = -EINVAL; - if ( !CONSOLE_ISOWNER(current) ) return -EPERM; + if ( !CONSOLE_ISOWNER(current) ) + return -EPERM; - switch(op) { - case KBD_OP_WRITEOUTPUT: - kbd_write_output(val); - return 0L; - case KBD_OP_WRITECOMMAND: - kbd_write_command(val); - return 0L; - case KBD_OP_READ: { - unsigned long flags; - unsigned long ret; spin_lock_irqsave(&kbd_lock, flags); - ret = kbd_ring_pop(); + + switch ( op ) + { + case KBD_OP_WRITEOUTPUT: + kbd_write_output(val); + ret = 0L; + break; + case KBD_OP_WRITECOMMAND: + kbd_write_command(val); + ret = 0L; + break; + case KBD_OP_READ: + ret = kbd_ring_pop(); + break; + } + spin_unlock_irqrestore(&kbd_lock, flags); - return ret; - } - } - return -EINVAL; + return ret; } static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) { - unsigned char status; - unsigned int work = 1000; - unsigned long cpu_mask; - unsigned long flags; - spin_lock_irqsave(&kbd_lock, flags); - status = kbd_read_status(); - -#ifdef KBD_DEBUG - printk("keyboard_interrupt irq %d, status 0x%2x\n", irq, status); -#endif - while ((--work > 0) && (status & KBD_STAT_OBF)) + unsigned char status, scancode; + unsigned int work = 1000; + unsigned long cpu_mask, flags; + + spin_lock_irqsave(&kbd_lock, flags); + + while ( (--work > 0) && ((status = kbd_read_status()) & KBD_STAT_OBF) ) { - unsigned char scancode; - scancode = kbd_read_input(); - //printk("scancode 0x%2x\n", scancode); + scancode = kbd_read_input(); #ifdef CONFIG_XEN_ATTENTION_KEY - if(!(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF))) { - if ((scancode & (~KBD_SCANCODE_KEYUP_MASK)) == XEN_ATTENTION_KEY) { - xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK); - //printk("xen_attention_key_down %d\n", xen_attention_key_down); - } else if (xen_attention_key_down) { - key_handler *handler; - unsigned char key; - - spin_unlock_irqrestore(&kbd_lock, flags); - key = convert_scancode(scancode); - if(key && (handler = get_key_handler(key))) - (*handler)(key, dev_id, regs); - - spin_lock_irqsave(&kbd_lock, flags); - status = kbd_read_status(); - continue; // do not send key to guest os - } - } + if ( !(status & (KBD_STAT_GTO | KBD_STAT_PERR | KBD_STAT_MOUSE_OBF)) ) + { + if ( (scancode & (~KBD_SCANCODE_KEYUP_MASK)) == XEN_ATTENTION_KEY ) + { + xen_attention_key_down = !(scancode & KBD_SCANCODE_KEYUP_MASK); + } + else if ( xen_attention_key_down ) + { + key_handler *handler; + unsigned char key; + spin_unlock_irqrestore(&kbd_lock, flags); + key = convert_scancode(scancode); + if ( key && (handler = get_key_handler(key)) ) + (*handler)(key, dev_id, regs); + spin_lock_irqsave(&kbd_lock, flags); + continue; + } + } #endif - if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) { - kbd_ring_push(status, scancode); - - cpu_mask = mark_guest_event(CONSOLE_OWNER, _EVENT_KBD); + kbd_ring_push(status, scancode); + cpu_mask = mark_guest_event(CONSOLE_OWNER, _EVENT_KBD); guest_event_notify(cpu_mask); - - status = kbd_read_status(); - //scancode = kbd_read_input(); - } } - if (!work) - printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status); + if ( !work ) + printk(KERN_ERR "xen_keyb: controller jammed (0x%02X).\n", status); spin_unlock_irqrestore(&kbd_lock, flags); } @@ -275,20 +229,20 @@ static void keyboard_interrupt(int irq, void *dev_id, struct pt_regs *regs) void initialize_keyboard() { - spin_lock_init(&kbd_lock); - - if(request_irq(KEYBOARD_IRQ, keyboard_interrupt, SA_NOPROFILE, "keyboard", NULL)) { - printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); - return; - } + spin_lock_init(&kbd_lock); - if(request_irq(AUX_IRQ, keyboard_interrupt, SA_NOPROFILE, "PS/2 Mouse", NULL)) { - printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ); - return; - } + if( request_irq(KEYBOARD_IRQ, keyboard_interrupt, + SA_NOPROFILE, "keyboard", NULL)) + { + printk("initialize_keyboard: failed to alloc IRQ %d\n", KEYBOARD_IRQ); + return; + } -#ifdef KBD_DEBUG - printk("PS/2 keyboard and mouse interface ok"); -#endif + if ( request_irq(AUX_IRQ, keyboard_interrupt, + SA_NOPROFILE, "PS/2 Mouse", NULL)) + { + printk("initialize_keyboard: failed to alloc IRQ %d\n", AUX_IRQ); + return; + } } diff --git a/xen/include/xeno/config.h b/xen/include/xeno/config.h index ac1051dad9..f1bc4c2000 100644 --- a/xen/include/xeno/config.h +++ b/xen/include/xeno/config.h @@ -38,6 +38,8 @@ #define CONFIG_SD_EXTRA_DEVS 40 #define CONFIG_SCSI_MULTI_LUN 1 +#define CONFIG_XEN_ATTENTION_KEY 1 + #define HZ 100 /* -- 2.30.2